读《Blob API》总结-2020.06.06
学习时间:2020.06.07
学习章节:Blob API
一、主要知识点
- 什么是Blob
- Blob 构造函数
- Blob 的属性与方法
- Blob 的拓展应用
- Blob 与 ArrayBuffer
- 各种类型之间的转换
1. 什么是 Blob
Blob(Binary Large Object) Blob 对象表示一个不可变、原始数据的类文件对象。File
接口基于Blob
,继承了 Blob 的功能并将其扩展使其支持用户系统上的文件。
一个 Blob 对象包含两个属性:size 与 type,如下:
一个 File 对象包含 lastModified、lastModifiedDate、size、type 与 webkitRelativePath 如下:
2. Blob 简介
2.1 构造函数
1 | var newBlob = new Blob(array, options); |
参数:
- array:ArrayBuffer,ArrayBufferView,Blob,USVString对象的数组等对象构成的数组,将被放入Blob中。USVString 对象会被编码成 UTF-8 。
- options:一个可选对象
- type:它是 MINE type 类型,将会被放到 blob 中,默认是空字符串。
- endings:默认值为 transparent,用于指定包含结束符
\n
的字符串如何被写入。
示例:
1 | var aFileParts = ['<a id="a"><b id="b">hey qhw!</b></a>']; // an array consisting of a single DOMString |
2.2 Blob 的属性
- Blob.size:
Blob
对象中所包含数据的大小(字节)。 - Blob.type:一个字符串,表明该
Blob
对象所包含数据的 MIME 类型。如果类型未知,则该值为空字符串。
2.3 Blob 的方法
- Blob.slice([start[, end[, contentType]]]):返回一个新的
Blob
对象,包含了源Blob
对象中指定范围内的数据。Blob 对象是不可改变的。我们不能直接在一个 Blob 中更改数据,但是我们 可以对一个 Blob 进行分割,从其中创建新的 Blob 对象,将它们混合到一个新的 Blob 中。 - Blob.stream():返回一个能读取blob内容的
ReadableStream
。 - Blob.text():返回一个promise且包含blob所有内容的UTF-8格式的
USVString
。 - Blob.arrayBuffer():返回一个promise且包含blob所有内容的二进制格式的
ArrayBuffer
3. Blob 的拓展应用
我们经常在上传文件的时候,会得到一个 file 对象,它基于 Blob。所以我们可以把它分块上传。也可以通过一些转换操作,来生成带水印的图片。最后再通过 formData 上传 Blob。
3.1 分块上传
这边使用 koa 作为服务端
服务端部分:
1 | const fs = require("fs"); |
前端部分:
1 |
|
3.2 图片添加水印
前端部分:
1 |
|
这边只是将图片转成 Base64 展示,如果需要上传,可以转成 Blob 对象做上传,来减少传输的数据量。下面会说各种类型之间的转换。
实现效果:
3.3 图片压缩
在我们选择本地图片上传之前,我们可以使用 Canvas 来对图片进行压缩。也就是使用添加水印功能中用到的 toDataURL
方法,它接受2个可选参数:
- type:图片格式,默认为
image/png
- encoderOptions:图片之类,取值范围为0-1,如果超出范围,默认为
0.92
压缩方法:
1 | const MAX_WIDTH = 600; // 图片最大宽度 |
我们可以用上面那个生成水印的图片分别测试压缩与未压缩的图片:
1 | ... |
可以看到设置 encoderOptions 为 .5 的时候,图片大小小了大概 37kb
4. Blob URL/Object URL
在上面水印的例子中我们使用 createObjectURL
方法得到Blob URL
1 | blob:http://localhost:8000/a9f10cc1-3a13-470d-bd34-bcccbcee9167 |
4.1 什么是 Blob URL/Object URL
Blob URL/Object URL 是一种伪协议,允许 Blob 和 File 对象用作图像,下载二进制数据连接等 URL 源,在浏览器中,我们使用 URL.createObjectURL
方法来创建它,该方法接收一个 Blob 对象,并为其创建一个唯一的 URL,形式为 blob:<origin>/<uuid>
,就跟上面的例子长的一样。
浏览器内部为每个通过 URL.createObjectURL
方法生成的 URL 存储了 URL -> Blob 的映射,因此,此类 URL 比较短,但可以访问 Blob。
4.2 Blob URL 的副作用
也正是因为 URL.createObjectURL
方法生成的 URL 存储了 URL -> Blob 的映射,Blob 本身驻留在内存中,浏览器无法释放。映射在文档卸载时自动清除,Blob 对象也会被释放。但是如果应用程序寿命较长,那不会很快就被释放。也就说我们创建了 Blob URL,不再需要使用该 Blob 的时候,它也在内存中。
解决方案:我们可以通过 URL.revokeObjectURL(url)
方法,从内部映射中删除引用,从而允许删除 Blob(在没有其他引用的情况下),从而释放内存。
5. Blob 与 ArrayBuffer
ArrayBuffer 对象:用于表示通用的,固定长度的原始二进制数据缓冲区。你不能直接操纵 ArrayBuffer 的内容,而是需要创建一个类型化数组对象或 DataView 对象,该对象以特定格式表示缓冲区,并使用该对象读取和写入缓冲区的内容。
Blob 类型的对象:表示不可变的类似文件对象的原始数据。Blob 表示的不一定是 JavaScript 原生格式的数据。File 接口基于 Blob,继承了Blob 功能并将其扩展为支持用户系统上的文件。
5.1 Blob vs ArrayBuffer
- 除非你需要使用 ArrayBuffer 提供的写入/编辑的能力,否则 Blob 格式可能是最好的。
- Blob 对象是不可变的,而 ArrayBuffer 是可以通过 TypedArrays 或 DataView 来操作。
- ArrayBuffer 是存在内存中的,可以直接操作。而 Blob 可以位于磁盘、高速缓存内存和其他不可用的位置。
- 虽然 Blob 可以直接作为参数传递给其他函数,比如
window.URL.createObjectURL()
。但是,你可能仍需要 FileReader 之类的 File API 才能与 Blob 一起使用。 - Blob 与 ArrayBuffer 对象之间是可以相互转化的:
- 使用 FileReader 的
readAsArrayBuffer()
方法,可以把 Blob 对象转换为 ArrayBuffer 对象; - 使用 Blob 构造函数,如
new Blob([new Uint8Array(data]);
,可以把 ArrayBuffer 对象转换为 Blob 对象。
- 使用 FileReader 的
二、知识点拓展
1. 各种类型之间的转换
可以先了解一下这两个方法
btoa:方法用于创建一个 base-64 编码的字符串。
atob:atob() 方法用于解码使用 base-64 编码的字符串。
1.1 img 转 canvas
1 | function imgtocanvas(img){ |
1.2 canvas 转 base64
1 | canvasElement.toDataURL("image/jpeg"); |
1.3 DataURL(base64)转blob
1 | function dataURLtoBlob(dataurl) { |
1.4 file(blob)转DataURL(base64)
1 | function filetoblob(file) { |
1.5 blob 转 blob URL
1 | var URL = |
1.6 blob URL 转 blob
1 | function URLtoblob(){ |
1.7 ArrayBuffer 转 blob
只需将 ArrayBuffer 作为参数传入即可
1 | const buffer = new ArrayBuffer(16); |
1.8 blob 转 ArrayBuffer
需要借助 FileReader
1 | const blob = new Blob([1, 2, 3, 4, 5]); |
2. FormData 设置 blob 上传
1 | var form= new FormData(); |